// Copyright (c) 2022 by Duguang.IO Inc. All Rights Reserved.
// Author: Ethan Liu
// Date: 2022-05-04 18:00:25

package engine

import (
	"io"
	"jianmu-worker-kube/types"
	"sync"
)

type (
	// Unit 执行单元定义
	Unit struct {
		K8sNode    bool
		Type       string    `json:"type,omitempty"`
		PodSpec    *PodSpec  `json:"pod_spec,omitempty"`
		Volume     *Volumes  `json:"volume,omitempty"`
		Volumes    []*Volume `json:"volumes,omitempty"`
		Secrets    []*Secret `json:"secrets,omitempty"`
		PullSecret *Secret   `json:"pull_secrets,omitempty"`
		Internal   []*Runner `json:"internal,omitempty"`
		Runners    []*Runner `json:"runners,omitempty"`

		TaskInstanceId string `json:"taskInstanceId,omitempty"`
		ResultFile     string `json:"resultFile,omitempty"`
		WorkerId       string
		//node      Node
		Resources      *Resources
		DataDir        string
		podUpdateMutex sync.Mutex
		WorkerData     string
		Log            io.Writer
		Stop           chan struct{}
	}

	Volumes struct {
		Name string `json:"name,omitempty"`
		Type string `json:"type,omitempty"`
	}
	// PodSpec
	PodSpec struct {
		Name               string            `json:"name,omitempty"`
		Namespace          string            `json:"namespace,omitempty"`
		Annotations        map[string]string `json:"annotations,omitempty"`
		Labels             map[string]string `json:"labels,omitempty"`
		NodeName           string            `json:"node_name,omitempty"`
		NodeSelector       map[string]string `json:"node_selector,omitempty"`
		Tolerations        []Toleration      `json:"tolerations,omitempty"`
		ServiceAccountName string            `json:"service_account_name,omitempty"`
		HostAliases        []HostAlias       `json:"host_aliases,omitempty"`
		DnsConfig          DnsConfig         `json:"dns_config,omitempty"`
	}

	// Runner 执行器定义
	Runner struct {
		ID      string `json:"taskInstanceId,omitempty"`
		Version int    `json:"version"`

		Command      []string          `json:"args,omitempty"`
		Detach       bool              `json:"detach,omitempty"`
		DependsOn    []string          `json:"depends_on,omitempty"`
		Entrypoint   string            `json:"entrypoint,omitempty"`
		Envs         map[string]string `json:"environment,omitempty"`
		IgnoreStdout bool              `json:"ignore_stderr,omitempty"`
		IgnoreStderr bool              `json:"ignore_stdout,omitempty"`
		Image        string            `json:"image,omitempty"`
		Name         string            `json:"name,omitempty"`
		Placeholder  string            `json:"placeholder,omitempty"`
		Privileged   bool              `json:"privileged,omitempty"`
		Resources    *Resources        `json:"resources,omitempty"`
		Pull         PullPolicy        `json:"pull,omitempty"`
		Secrets      []*SecretVar      `json:"secrets,omitempty"`
		SpecSecrets  []*Secret         `json:"spec_secrets,omitempty"`
		User         *int64            `json:"user,omitempty"`
		Group        *int64            `json:"group,omitempty"`
		Volumes      []*VolumeMount    `json:"volumes,omitempty"`
		WorkingDir   string            `json:"working_dir,omitempty"`
		Cmd          []string          `json:"-"`
	}

	// Secret 密钥
	Secret struct {
		Name string `json:"name,omitempty"`
		Data string `json:"data,omitempty"`
		Mask bool   `json:"mask,omitempty"`
	}

	// SecretVar
	SecretVar struct {
		Name string `json:"name,omitempty"`
		Env  string `json:"env,omitempty"`
	}

	// Platform defines the target platform.
	Platform struct {
		OS      string `json:"os,omitempty"`
		Arch    string `json:"arch,omitempty"`
		Variant string `json:"variant,omitempty"`
		Version string `json:"version,omitempty"`
	}

	Volume struct {
		EmptyDir    *VolumeEmptyDir    `json:"temp,omitempty"`
		HostPath    *VolumeHostPath    `json:"host,omitempty"`
		DownwardAPI *VolumeDownwardAPI `json:"downward_api,omitempty"`
		Claim       *VolumeClaim       `json:"claim,omitempty"`
		ConfigMap   *VolumeConfigMap   `json:"config_map,omitempty"`
		Secret      *VolumeSecret      `json:"secret,omitempty"`
	}

	// VolumeMount describes a mounting of a Volume
	// within a container.
	VolumeMount struct {
		Name     string `json:"name,omitempty"`
		Path     string `json:"path,omitempty"`
		SubPath  string `json:"sub_path,omitempty"`
		ReadOnly bool   `json:"read_only,omitempty"`
	}

	// VolumeEmptyDir mounts a temporary directory from the
	// host node's filesystem into the container. This can
	// be used as a shared scratch space.
	VolumeEmptyDir struct {
		ID        string `json:"id,omitempty"`
		Name      string `json:"name,omitempty"`
		Medium    string `json:"medium,omitempty"`
		SizeLimit int64  `json:"size_limit,omitempty"`
	}

	// VolumeHostPath mounts a file or directory from the
	// host node's filesystem into your container.
	VolumeHostPath struct {
		ID   string `json:"id,omitempty"`
		Name string `json:"name,omitempty"`
		Path string `json:"path,omitempty"`
	}
	// VolumeDownwardAPI ...
	VolumeDownwardAPI struct {
		ID    string                  `json:"id,omitempty"`
		Name  string                  `json:"name,omitempty"`
		Items []VolumeDownwardAPIItem `json:"items,omitempty"`
	}
	// VolumeDownwardAPIItem ...
	VolumeDownwardAPIItem struct {
		Path      string `json:"path,omitempty"`
		FieldPath string `json:"field_path,omitempty"`
	}

	// VolumeClaim ...
	VolumeClaim struct {
		ID        string `json:"id,omitempty"`
		Name      string `json:"name,omitempty"`
		ClaimName string `json:"claim_name,omitempty"`
		ReadOnly  bool   `json:"read_only,omitempty"`
	}

	// VolumeConfigMap ...
	VolumeConfigMap struct {
		ID            string `json:"id,omitempty"`
		Name          string `json:"name,omitempty"`
		ConfigMapName string `json:"config_map_name,omitempty"`
		DefaultMode   int32  `json:"default_mode,omitempty"`
		Optional      bool   `json:"optional,omitempty"`
	}

	// VolumeSecret ...
	VolumeSecret struct {
		ID          string `json:"id,omitempty"`
		Name        string `json:"name,omitempty"`
		SecretName  string `json:"secret_name,omitempty"`
		DefaultMode int32  `json:"default_mode,omitempty"`
		Optional    bool   `json:"optional,omitempty"`
	}

	// Resources describes the compute resource requirements.
	Resources struct {
		Limits   *ResourceObject `json:"limits,omitempty"`
		Requests *ResourceObject `json:"requests,omitempty"`
	}

	// ResourceObject describes compute resource requirements.
	ResourceObject struct {
		CPU    string `json:"cpu"`
		Memory string `json:"memory"`
	}

	// HostAlias
	HostAlias struct {
		IP        string   `json:"ip,omitempty"`
		Hostnames []string `json:"hostnames,omitempty"`
	}

	// Toleration
	Toleration struct {
		Effect            string `json:"effect,omitempty"`
		Key               string `json:"key,omitempty"`
		Operator          string `json:"operator,omitempty"`
		TolerationSeconds *int   `json:"toleration_seconds,omitempty"`
		Value             string `json:"value,omitempty"`
	}
	// DnsConfig
	DnsConfig struct {
		Nameservers []string           `json:"nameservers,omitempty"`
		Searches    []string           `json:"searches,omitempty"`
		Options     []DNSConfigOptions `json:"options,omitempty"`
	}

	DNSConfigOptions struct {
		Name  string  `json:"name,omitempty"`
		Value *string `json:"value,omitempty"`
	}

	// Line 容器日志行
	Line struct {
		Number    int    `json:"number"`
		Message   string `json:"content"`
		Timestamp int64  `json:"timestamp"`
	}

	Task struct {
		TaskId     string     `json:"taskId,omitempty"`
		Status     TaskStatus `json:"status"`
		ExitCode   int        `json:"exitCode"`
		ResultFile string     `json:"resultFile,omitempty"`
		ErrorMsg   string     `json:"errorMsg,omitempty"`
		WorkData   string     `json:"workData,omitempty"`
	}

	Worker struct {
		// Worker ID
		ID string
		// Worker Name
		Name string `json:"name,omitempty"`
		// Worker Type
		Type string `json:"type,omitempty"`
		// worker tags
		Tag string `json:"tag,omitempty"`
	}

	// State 容器执行情况
	State struct {
		// ExitCode 退出代码
		ExitCode int

		// GetExited 是否已退出
		Exited bool

		// OOMKilled 是否被OOMKill终止
		OOMKilled bool

		// ResultFile 结果文件
		ResultFile string
	}
)

//
// implements the Secret interface
//

func (s *Secret) GetName() string  { return s.Name }
func (s *Secret) GetValue() string { return string(s.Data) }
func (s *Secret) IsMasked() bool   { return s.Mask }

//
// implements the Runner interface
//

func (r *Runner) GetSecretAt(i int) types.Secret { return r.SpecSecrets[i] }
func (r *Runner) GetSecretLen() int              { return len(r.SpecSecrets) }
